package evemanutool.utils.calc;
import java.util.ArrayList;
import java.util.Date;
import com.beimin.eveapi.shared.industryjobs.ApiIndustryJob;
import evemanutool.constants.DBConstants;
import evemanutool.constants.UserPrefConstants;
import evemanutool.data.cache.CorpProductionEntry;
import evemanutool.data.cache.TradeEntry;
import evemanutool.data.cache.WalletTransactionEntry;
import evemanutool.data.database.Blueprint;
import evemanutool.data.database.Item;
import evemanutool.data.database.ManuQuote;
import evemanutool.data.database.Material;
import evemanutool.data.display.Asset;
import evemanutool.data.display.CorpProductionQuote;
import evemanutool.data.display.MarketOrder;
import evemanutool.data.display.Supply;
import evemanutool.prefs.Preferences;
import evemanutool.prefs.Preferences.Account;
import evemanutool.prefs.Preferences.BlueprintStat;
import evemanutool.utils.databases.BlueprintDB;
import evemanutool.utils.databases.CorpApiDB;
import evemanutool.utils.databases.ItemDB;
import evemanutool.utils.databases.PriceDB;
import evemanutool.utils.databases.TechDB;
public class ProductionCalculator implements UserPrefConstants, DBConstants {
public static void updateProductionQuote(CorpProductionQuote q) {
//Updates user affected values.
int needToProduce = q.getSellTarget() - q.getOnSale() - q.getInProduction() - q.getStock(); //Set to 0 if over-stocked (negative).
q.setNeedToProduce(needToProduce > 0 ? needToProduce : 0);
}
public static CorpProductionQuote calculateProductionQuoteFromQuote(ManuQuote quote, BlueprintDB bdb,
PriceDB pdb, CorpApiDB cdb, Preferences prefs) {
//Calculate production numbers.
int stock = calculateItemStock(AssetCalculator.getFlatAssetsInCorpHangar(
cdb.getFlatAssets(), prefs.getAccountIndex(Account.INDUSTRY_HANGAR)),
quote.getBpo().getProduct().getTypeId());
int onSale = calculateItemOnSale(cdb.getSellOrders(), quote.getBpo().getProduct().getTypeId());
int inProduction = calculateItemInProduction(cdb.getIndustryJobs(), quote.getBpo());
return new CorpProductionQuote(quote, calculateAvgWeekTradeVolume(quote.getBpo().getProduct(), pdb),
calculateAvgWeekCorpSoldAmount(quote.getBpo().getProduct(), cdb, prefs),
true, stock, onSale, inProduction, 0, 0);
}
public static CorpProductionQuote calculateProductionQuoteFromRaw(CorpProductionEntry cMQE, BlueprintDB bdb,
PriceDB pdb, ItemDB idb, TechDB tdb, CorpApiDB cdb, Preferences prefs) {
//Temporary variables.
ManuQuote quote;
ManuQuote oldQuote;
Blueprint b = bdb.getByBlueprintId(cMQE.getBpoTypeId());
ArrayList<Material> matList = new ArrayList<>();
ArrayList<ManuQuote> matQuotes = new ArrayList<>();
//Setup an oldQuote to get the right material acquires.
//Initiate sub parts.
for (Integer typeId : cMQE.getManuMaterials()) {
matList.add(new Material(idb.getItem(typeId), 1));
}
oldQuote = new ManuQuote(null, null, 0, 0, 0, 0, 0, 0, matList, null, null);
//Create main quote.
b.setMe(prefs.getBlueprintStat(BlueprintStat.MOD_ME));
b.setPe(prefs.getBlueprintStat(BlueprintStat.MOD_PE));
quote = QuoteCalculator.calculateGenericQuote(b , 1, oldQuote, pdb, idb, bdb, tdb, prefs,
MAT_ACQUIRE_PRIO_ENUM[cMQE.getMatIndex()], INV_PRIO_ENUM[cMQE.getSpecIndex()], REV_PRIO_ENUM[cMQE.getSpecIndex()]);
//Create produced-material quotes.
for (Material m : quote.getMatList()) {
if (m.isProduced()) {
matQuotes.add(QuoteCalculator.calculateQuote(bdb.getByProductId(m.getItem().getTypeId()), (int) m.getAmount(), null, pdb, bdb, prefs,
MAT_ACQUIRE_PRIO_ENUM[cMQE.getMatIndex()]));
}
}
//Calculate production numbers.
int stock = calculateItemStock(AssetCalculator.getFlatAssetsInCorpHangar(
cdb.getFlatAssets(), prefs.getAccountIndex(Account.INDUSTRY_HANGAR)),
quote.getBpo().getProduct().getTypeId());
int onSale = calculateItemOnSale(cdb.getSellOrders(), quote.getBpo().getProduct().getTypeId());
int inProduction = calculateItemInProduction(cdb.getIndustryJobs(), quote.getBpo());
int needToProduce = cMQE.getSellTarget() - onSale - inProduction - stock; //Set to 0 if over-stocked (negative).
return new CorpProductionQuote(quote, calculateAvgWeekTradeVolume(quote.getBpo().getProduct(), pdb),
calculateAvgWeekCorpSoldAmount(quote.getBpo().getProduct(), cdb, prefs),
true, stock, onSale, inProduction,
needToProduce > 0 ? needToProduce : 0, cMQE.getSellTarget());
}
public static double calculateMaterialCoverage(Material m, long needed,
ArrayList<Supply> supplies) {
//Calculates the percentage as a double where 0 <= ans <= 1.
double stock = 0, req = 0;
for (Material m1 : m.getManufactureQuote().getMatList()) {
//Add required stock.
req += m1.getAmount() * needed;
for (Supply supply : supplies) {
if (supply.getItem().getTypeId() == m.getItem().getTypeId()) {
//Add owned stock but only as much as is required, not more.
stock += supply.getStock() > m1.getAmount() * needed ? m1.getAmount() * needed : supply.getStock();
}
}
}
return stock / req;
}
private static int calculateAvgWeekCorpSoldAmount(Item item, CorpApiDB cdb, Preferences prefs) {
int amount = 0;
//Earliest record included in calculations.
Date earliestRecord = new Date();
Date now = new Date();
for (WalletTransactionEntry wT :
cdb.getWalletTransactions().get(DIVISION_KEYS[prefs.getAccountIndex(Account.INDUSTRY_WALLET)])) {
if (wT.getTypeId() == item.getTypeId()) {
if (now.getTime() - wT.getDate().getTime() < MILLIS_IN_MONTH) {
if (wT.getDate().before(earliestRecord)) {
//Sets the date if earlier.
earliestRecord = wT.getDate();
}
amount += wT.getQuantity();
}
}
}
//Calculate the number of weeks data span over.
double weeks = (now.getTime() - earliestRecord.getTime()) / ((double) MILLIS_IN_MONTH / WEEKS_IN_MONTH);
return (int) (weeks != 0 ? (amount / weeks) + 0.5 : 0);
}
private static int calculateAvgWeekTradeVolume(Item i, PriceDB pdb) {
//Calculates the average sold over a week.
long volume = 0;
for (TradeEntry tE : pdb.getSellTH(i.getTypeId()).getHistory()) {
volume += tE.getVolume();
}
return (int) (volume / ((double) pdb.getSellTH(i.getTypeId()).getHistory().size() / DAYS_IN_WEEK) + 0.5);
}
private static int calculateItemInProduction(ArrayList<ApiIndustryJob> industryJobs, Blueprint b) {
int count = 0;
//Count the number of the given type in the assets.
for (ApiIndustryJob aIJ : industryJobs) {
if (aIJ.getInstalledItemTypeID() == b.getBlueprintItem().getTypeId()) {
count += aIJ.getRuns() * b.getProduct().getPortionSize();
}
}
return count;
}
private static int calculateItemOnSale(ArrayList<MarketOrder> sellOrders, int typeId) {
int count = 0;
//Count the number of the given type in the assets.
for (MarketOrder mO : sellOrders) {
if (mO.getItem().getTypeId() == typeId) {
count += mO.getMarketOrder().getVolRemaining();
}
}
return count;
}
private static int calculateItemStock(ArrayList<Asset> hangarAssets, int typeId) {
int count = 0;
//Count the number of the given type in the assets.
for (Asset a : hangarAssets) {
if (a.getItem().getTypeId() == typeId) {
count += a.getQuantity();
}
}
return count;
}
}